/*
    经过测试发现，在node环境下，首先可以假设有同步任务队列，宏任务队列，微任务队列
    宏任务队列主要可以分为以下几种：timer，poll，check
    按照以往的理解，在浏览器的时候，宏任务的代表——setTimeout
    每次执行完成后，会查看当前微任务队列是否为空，如果为空，就会执行微任务队列的任务，直到当前任务清空
    在node环境下，宏任务队列可以想象成一个这样的数组[...timer,...poll,...check],
    每个宏任务结束的时候，会检查微任务队列是否有任务，没有的话就会按顺序执行，执行完timer，再执行poll，再执行check
    注意，这和微任务队列不同，微任务队列当有新的任务的时候，会直接推送到队列末尾，所以会出现一连串的then的时候停不下来
    但是宏任务不一样，例如在timer队列时，如果出现了新的timer任务，会添加到一个新的数组中，而不是在当前的timer队列末尾添加

    这是第一个区别：宏任务再执行当前栈时，添加的新任务会轮到下一轮

    然后是setImmediate的执行时间，该执行时间是在check阶段，同样也遵守上面的第一个区别
    
    最后是process.nextTick的作用，该作用是在当前执行栈结束之后，下一个执行栈开始执行之前进行调用
    例如同步队列 ———> 微任务队列，微任务队列 ————> 宏任务队列，宏任务队列 ————> 微任务队列，宏任务 ————> 宏任务

    第二个区别：在process.nextTick中，同步队列和微任务队列之间是以队列为单位执行，而宏任务之间是以一个小任务为单位执行
*/

const promise = Promise.resolve();

setTimeout(() => {
    console.log("setTimeout1");
    setImmediate(() => {
        console.log("setImmediate1");
        setImmediate(() => {
            console.log("setImmediate2");
            process.nextTick(() => {
                console.log("nextTick4");
            });
        });
        promise
            .then(() => {
                console.log("promise3");
                process.nextTick(() => {
                    console.log("nextTick3");
                });
            })
            .then(() => {
                console.log("promise4");
            })
        setImmediate(() => {
            console.log("setImmediate3");
        });
    });
    process.nextTick(() => {
        console.log("nextTick1");
    });
    promise.then(() => {
        console.log("promise1");
        process.nextTick(() => {
            console.log("nextTick2");
        });
    });
    promise.then(() => {
        console.log("promise2");
    });
}, 0);

setTimeout(() => {
    console.log("setTimeout2");
    setTimeout(() => {
        console.log("setTimeout3");
    }, 0);
    const newTime = new Date().getTime();
    while (true) {
        if (new Date().getTime() - newTime > 1000) {
            break;
        }
    }
}, 0);

const time = new Date().getTime();
while (true) {
    if (new Date().getTime() - time > 1000) {
        break;
    }
}
